<template>
  <div :class="theme">
    <div :ref="uuid + 'layer'" class="w-dialog">
      <div v-show="hasHead" :ref="uuid + 'layer-head'" class="w-dialog-head">
        <template v-if="!HeadCom">
          <span class="dialog-head-title">{{ title }}</span>
          <span class="dialog-head-btn">
            <i v-show="canmin" @click="min" class="head-btn-min"></i>
            <i v-show="canmax" @click="max" class="head-btn-max"></i>
            <i v-show="canreset" @click="reset" class="head-btn-reset"></i>
            <i @click="close" class="head-btn-close"></i>
          </span>
        </template>
        <template v-else>
          <component
            v-bind:is="HeadCom"
            :subData="customHead.subData"
          ></component>
        </template>
      </div>
      <div :ref="uuid + 'layer-body'" class="w-dialog-body">
        <component v-bind:is="bodyCom" :subData="content.subData"></component>
      </div>
    </div>
    <div
      v-show="shade"
      :ref="uuid + 'layer-shade'"
      class="w-dialog-shade"
    ></div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      ismin: false,
      ismax: false,
      lastState: {
        left: 0,
        top: 0,
        with: 0,
        height: 0,
      },
      baseZ: 9000,
    };
  },
  computed: {
    dom_layer() {
      return this.$refs[this.uuid + "layer"];
    },
    dom_head() {
      return this.$refs[this.uuid + "layer-head"];
    },
    dom_body() {
      return this.$refs[this.uuid + "layer-body"];
    },
    dom_shade() {
      return this.$refs[this.uuid + "layer-shade"];
    },
    layer_z() {
      return this.baseZ + this[this.name].layer_z;
    },
    canmin() {
      return this.hasMin && !this.ismin && !this.ismax;
    },
    canmax() {
      return this.hasMax && !this.ismax && !this.ismin;
    },
    canreset() {
      return this.ismin || this.ismax;
    },
  },
  props: {
    uuid: {
      type: String,
      default: undefined,
    },
    //弹框大小
    area: {
      type: Object,
      default() {
        return {
          height: "auto",
          width: "auto",
        };
      },
    },
    //弹框位置，可由对象指定,为空则默认居中显示
    location: {
      type: Object,
      default() {
        return {
          top: null,
          left: null,
          bottom: null,
          right: null,
        };
      },
    },
    shade: {
      type: Boolean,
      default: false,
    },
    blank: {
      type: Boolean,
      default: true,
    },
    move: {
      type: Boolean,
      default: false,
    },
    hasHead: {
      type: Boolean,
      default: true,
    },
    hasMin: {
      type: Boolean,
      default: true,
    },
    hasMax: {
      type: Boolean,
      default: true,
    },
    bottomOff: {
      type: Number,
      default: 0,
    },
    leftOff: {
      type: Number,
      default: 0,
    },
    minHight: {
      type: Number,
      default: 50,
    },
    minWidth: {
      type: Number,
      default: 200,
    },
    rowGap: {
      type: Number,
      default: 20,
    },
    colGap: {
      type: Number,
      default: 20,
    },
    title: {
      type: String,
      default: undefined,
    },
    name: {
      type: String,
      default: undefined,
    },
    customHead: {
      type: Object,
      default() {
        return {
          type: "vue",
          subCom: undefined,
          subData: undefined,
        };
      },
    },
    content: {
      type: Object,
      default() {
        return {
          type: "vue",
          subCom: undefined,
          subData: undefined,
        };
      },
    },
    theme: {
      type: String,
      default: undefined,
    },
    success: {
      type: Function,
      default: undefined,
    },
    cancel: {
      type: Function,
      default: undefined,
    },
    minBack: {
      type: Function,
      default: undefined,
    },
    maxBack: {
      type: Function,
      default: undefined,
    },
    restore: {
      type: Function,
      default: undefined,
    },
    HeadCom: {
      type: String,
      default: undefined,
    },
    bodyCom: {
      type: String,
      default: undefined,
    },
  },
  methods: {
    //记录快照
    initSnapshot() {
      this.lastState.left = this.dom_layer.offsetLeft;
      this.lastState.top = this.dom_layer.offsetTop;
      this.lastState.with = this.dom_layer.offsetWidth;
      this.lastState.height = this.dom_layer.offsetHeight;
      console.log(this.lastState);
    },
    initState(state) {
      state = state || this.lastState;
      this.dom_layer.style.right = "auto";
      this.dom_layer.style.bottom = "auto";
      this.dom_layer.style.top = state.top + "px";
      this.dom_layer.style.left = state.left + "px";
      this.dom_layer.style.width = state.with + "px";
      this.dom_layer.style.height = state.height + "px";
    },
    //关闭
    close() {
      this[this.name].close(this);
    },
    //更新位置
    updateLayers() {
      var layers = this[this.name].min_layer;
      var mincount = 0;
      var win_width = document.documentElement.clientWidth - this.leftOff;
      var max_col = Math.floor(win_width / this.minWidth);
      for (var key in layers) {
        var row = Math.floor(mincount / max_col);
        layers[key].style.bottom =
          this.bottomOff + row * (this.minHight + this.rowGap) + "px";
        layers[key].style.left =
          this.leftOff +
          (mincount - row * max_col) * (this.minWidth + this.colGap) +
          "px";
        mincount++;
      }
    },
    //最小化
    min() {
      this.initSnapshot(); //记录快照
      this.dom_head.style.height = "100%";
      var mincount = this[this.name].getminNum(); //获取数量
      var win_width = document.documentElement.clientWidth - this.leftOff;
      var max_col = Math.floor(win_width / this.minWidth);
      var row = Math.floor(mincount / max_col);
      this.dom_layer.style.top = "auto";
      this.dom_layer.style.right = "auto";
      this.dom_layer.style.bottom =
        this.bottomOff + row * (this.minHight + this.rowGap) + "px";
      this.dom_layer.style.left =
        this.leftOff +
        (mincount - row * max_col) * (this.minWidth + this.colGap) +
        "px";
      this.dom_layer.style.width = this.minWidth + "px";
      this.dom_layer.style.height = this.minHight + "px";
      this.dom_body.style.display = "none";
      this.ismin = true;
      this[this.name].addminNum(this.uuid, this.dom_layer);
      if (this[this.name].getminNum() > 1) {
        this.updateLayers(); //重新排版
      }

      if (typeof this.minBack == "function") {
        this.minBack();
      }
    },
    //最大化
    max() {
      this.dom_head.style.height = "50px";
      this.initSnapshot();
      this.dom_layer.style.top = 0 + "px";
      this.dom_layer.style.left = 0 + "px";
      this.dom_layer.style.width = "100%";
      this.dom_layer.style.height = "100%";
      this.ismax = true;
      if (typeof this.maxBack == "function") {
        this.maxBack();
      }
    },
    //还原
    reset() {
      if (this.ismin) {
        this.dom_head.style.height = "50px";
        this.dom_body.style.display = "block";
        this[this.name].minusminNum(this.uuid);
      }
      this.initState();
      this.ismin = false;
      this.ismax = false;
      if (typeof this.restore == "function") {
        this.restore();
      }
    },
    auto_z() {
      if (this.shade) {
        this.dom_shade.style["z-index"] = this.layer_z;
      }
      this.dom_layer.style["z-index"] = this.layer_z + 1;
    },
    //设置大小
    auto_area(area) {
      area = area || this.area;
      this.dom_layer.style.width = area.width;
      this.dom_layer.style.height = area.height;
    },
    auto_center() {
      var dom = this.dom_layer;
      var CHeight = document.documentElement.clientHeight;
      var CWidth = document.documentElement.clientWidth;
      var PHeight = dom.offsetHeight;
      var PWidth = dom.offsetWidth;
      dom.style.top = (CHeight > PHeight ? (CHeight - PHeight) / 2 : 0) + "px";
      dom.style.left = (CWidth - PWidth) / 2 + "px";
    },
    auto_location(location) {
      location = location || this.location;
      if (location.top && location.left) {
        this.dom_layer.style.bottom = null;
        this.dom_layer.style.right = null;
        this.dom_layer.style.top = location.top;
        this.dom_layer.style.left = location.left;
        return;
      }
      if (location.bottom && location.right) {
        this.dom_layer.style.top = null;
        this.dom_layer.style.left = null;
        this.dom_layer.style.bottom = location.bottom;
        this.dom_layer.style.right = location.right;
      }
    },
  },
  created() {
    if (typeof this.success == "function") {
      this.success();
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.auto_z(); //设置Z值
      this.auto_area(); //设置弹框大小
      this.auto_center(); //水平垂直居中
      this.auto_location(); //位置设置
      this.initSnapshot(); //记录位置状态
      if (this.move && this.hasHead) {
        this[this.name].dragBind(this.dom_head, this.dom_layer);
      }
      if (this.shade && this.blank) {
        this.dom_shade.addEventListener("click", this.close);
      }
    });
  },
  beforeDestroy() {
    console.log("我被beforeDestroy了");
    if (this.move && this.hasHead) {
      this.dom_head.onmousedown = null;
    }
    if (this.shade && this.blank) {
      this.dom_shade.removeEventListener("click", this.close);
    }
    if (typeof this.cancel == "function") {
      this.cancel();
    }
  },
};
</script>

<style>
.w-dialog {
  width: 600px;
  height: 600px;
  z-index: 999;
  position: fixed;
  border-radius: 2px;
  box-shadow: 0 1px 3px rgb(0 0 0 / 30%);
  box-sizing: border-box;
  background-color: #fff;
}

.w-dialog-head {
  width: 100%;
  text-align: center;
  cursor: default;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #e3e6e8;
  box-sizing: border-box;
  height: 50px;
  padding-left: 16px;
  padding-right: 16px;
  overflow: auto;
}
.dialog-head-title {
  line-height: 24px;
  font-size: 18px;
  font-weight: 400;
  color: #303133;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  position: relative;
  width: calc(100% - 60px);
  text-align: left;
}
.dialog-head-btn {
  display: flex;
}
.head-btn-close {
  color: #909399;
  font-weight: 400;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
  vertical-align: baseline;
  display: inline-block;
  background-image: url("./imgs/close.png");
  width: 24px;
  height: 24px;
  background-size: cover;
  cursor: pointer;
}
.head-btn-close:hover {
  background-image: url("./imgs/close-hover.png");
}
.head-btn-max {
  color: #909399;
  font-weight: 400;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
  vertical-align: baseline;
  display: inline-block;
  background-image: url("./imgs/max.png");
  width: 24px;
  height: 24px;
  background-size: cover;
  cursor: pointer;
  margin: 0 4px;
}
.head-btn-max:hover {
  background-image: url("./imgs/max-hover.png");
}
.head-btn-min {
  color: #909399;
  font-weight: 400;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
  vertical-align: baseline;
  display: inline-block;
  background-image: url("./imgs/min.png");
  width: 24px;
  height: 24px;
  background-size: cover;
  cursor: pointer;
}
.head-btn-min:hover {
  background-image: url("./imgs/min-hover.png");
}
.head-btn-reset {
  color: #909399;
  font-weight: 400;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
  vertical-align: baseline;
  display: inline-block;
  background-image: url("./imgs/reset.png");
  width: 24px;
  height: 24px;
  background-size: cover;
  cursor: pointer;
  margin: 0 4px;
}
.head-btn-reset:hover {
  background-image: url("./imgs/reset-hover.png");
}
.w-dialog-body {
  width: 100%;
  padding: 16px;
  height: calc(100% - 50px);
  overflow: auto;
}
.w-dialog-shade {
  position: fixed;
  left: 0;
  top: 0;
  background: rgba(0, 0, 0, 0.3);
  width: 100%;
  height: 100%;
  z-index: 100;
}
</style>
